/**
 * Diagram Wrapper组件
 * */

import * as go from 'gojs/release/go';
import {ReactDiagram} from 'gojs-react/lib/types';
import * as React from 'react';


export class DiagramWrapper extends React.Component {
  /**
   * Ref to keep a reference to the component, which provides access to the GoJS diagram via getDiagram().
   */

  constructor(props) {
    super(props);
    this.diagramRef = React.createRef();
  }

  /**
   * Get the diagram reference and add any desired diagram listeners.
   * Typically the same function will be used for each listener,
   * with the function using a switch statement to handle the events.
   * This is only necessary when you want to define additional app-specific diagram listeners.
   */
  componentDidMount() {

    if (!this.diagramRef.current) return;
    const diagram = this.diagramRef.current.getDiagram();
    if (diagram instanceof go.Diagram) {
      diagram.addDiagramListener('ChangedSelection', this.props.onDiagramEvent);
    }
    console.log(this.diagramRef)
  }

  /**
   * Get the diagram reference and remove listeners that were added during mounting.
   * This is only necessary when you have defined additional app-specific diagram listeners.
   */
  componentWillUnmount() {
    if (!this.diagramRef.current) return;
    const diagram = this.diagramRef.current.getDiagram();
    if (diagram instanceof go.Diagram) {
      diagram.removeDiagramListener('ChangedSelection', this.props.onDiagramEvent);
    }
  }


  /**
   * Diagram initialization method, which is passed to the ReactDiagram component.
   * This method is responsible for making the diagram and initializing the model, any templates,
   * and maybe doing other initialization tasks like customizing tools.
   * The model's data should not be set here, as the ReactDiagram component handles that via the other props.
   */
  initDiagram = () => {
    const $ = go.GraphObject.make;
    const diagram =
      $(go.Diagram,
        {
          'undoManager.isEnabled': true,  // enable undo & redo
          'clickCreatingTool.archetypeNodeData': {text: 'new node', color: 'lightblue'},
          model: $(go.GraphLinksModel,
            {
              linkKeyProperty: 'key',  // IMPORTANT! must be defined for merges and data sync when using GraphLinksModel

            })
        });


    function changeColor(e, obj) {
      diagram.commit(function (d) {
        // get the context menu that holds the button that was clicked
        let contextmenu = obj.part;
        // get the node data to which the Node is data bound
        let nodedata = contextmenu.data;
        // compute the next color for the node
        let newcolor = "lightblue";
        switch (nodedata.color) {
          case "lightblue":
            newcolor = "lightgreen";
            break;
          case "lightgreen":
            newcolor = "lightyellow";
            break;
          case "lightyellow":
            newcolor = "orange";
            break;
          case "orange":
            newcolor = "lightblue";
            break;
        }
        // modify the node data
        // this evaluates data Bindings and records changes in the UndoManager
        d.model.set(nodedata, "color", newcolor);
      }, "changed color");
    }

    // define a simple Node template
    diagram.nodeTemplate =
      $(go.Node, "Auto",
        {
          click: function (e, node) {
            // highlight all Links and Nodes coming out of a given Node
            var diagram = node.diagram;
            diagram.startTransaction("highlight");
            // remove any previous highlighting
            diagram.clearHighlighteds();
            // for each Link coming out of the Node, set Link.isHighlighted
            node.findLinksOutOf().each(function (l) {
              l.isHighlighted = true;
            });
            // for each Node destination for the Node, set Node.isHighlighted
            node.findNodesOutOf().each(function (n) {
              n.isHighlighted = true;
            });
            diagram.commitTransaction("highlight");
          }
        },
        {
          contextMenu:     // define a context menu for each node
            $("ContextMenu",  // that has one button
              $("ContextMenuButton",
                $(go.TextBlock, "Change Colorn br ssssssssssssssss"),
                {click: changeColor})
              // more ContextMenuButtons would go here
            )  // end Adornment
        },
        $(go.Shape, "Rectangle", {fill: "lightgray"}),
        $(go.Panel, "Table",
          $(go.RowColumnDefinition,
            {column: 0, alignment: go.Spot.Left}),
          $(go.RowColumnDefinition,
            {column: 2, alignment: go.Spot.Right}),
          $(go.TextBlock,
            {
              column: 0, row: 0, columnSpan: 3, alignment: go.Spot.Center,
              font: "bold 10pt sans-serif", margin: new go.Margin(4, 2)
            },
            new go.Binding("text", "key")),
          $(go.Panel, "Horizontal",
            {column: 0, row: 1},
            $(go.Shape,
              {
                width: 6, height: 6, portId: "A", toSpot: go.Spot.Left,
                toLinkable: true, toMaxLinks: 1
              }),
            $(go.TextBlock, "A")
          ),
          $(go.Panel, "Horizontal",
            {column: 0, row: 2},
            $(go.Shape,
              {
                width: 6, height: 6, portId: "B", toSpot: go.Spot.Left,
                toLinkable: true, toMaxLinks: 1
              }),
            $(go.TextBlock, "B")
          ),
          $(go.Panel, "Horizontal",
            {column: 2, row: 1, rowSpan: 2},
            $(go.TextBlock, "Out"),
            $(go.Shape,
              {
                width: 6, height: 6, portId: "Out", fromSpot: go.Spot.Right,
                fromLinkable: true
              })
          )
        )
      )
    ;

    // relinking depends on modelData
    diagram.linkTemplate =
      $(go.Link,
        {routing: go.Link.Orthogonal, corner: 3},
        $(go.Shape,
          // the Shape.stroke color depends on whether Link.isHighlighted is true
          new go.Binding("stroke", "isHighlighted", function (h) {
            return h ? "red" : "black";
          })
            .ofObject(),
          // the Shape.strokeWidth depends on whether Link.isHighlighted is true
          new go.Binding("strokeWidth", "isHighlighted", function (h) {
            return h ? 3 : 1;
          })
            .ofObject()),
        $(go.Shape,
          {toArrow: "Standard", strokeWidth: 0},
          // the Shape.fill color depends on whether Link.isHighlighted is true
          new go.Binding("fill", "isHighlighted", function (h) {
            return h ? "red" : "black";
          })
            .ofObject())
      );


    diagram.layout = $(go.LayeredDigraphLayout, {columnSpacing: 10});

    diagram.toolManager.linkingTool.temporaryLink.routing = go.Link.Orthogonal;
    diagram.click = function (e) {
      e.diagram.commit(function (d) {
        d.clearHighlighteds();
      }, "no highlighteds");
    };
    return diagram;
  };

  render() {
    return (
      <ReactDiagram
        ref={this.diagramRef}
        divClassName='diagram-component'
        initDiagram={this.initDiagram}
        nodeDataArray={this.props.nodeDataArray}
        linkDataArray={this.props.linkDataArray}
        modelData={this.props.modelData}
        onModelChange={this.props.onModelChange}
        skipsDiagramUpdate={this.props.skipsDiagramUpdate}
      />
    );
  }
}